﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Resources;
using System.Windows.Markup;
using System.Reflection;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows.Threading;

namespace Jok.Client.Loader
{
    /// <summary>
    /// Manages the package list download process - takes a package list and loader interface as parameters and manage the download process
    /// </summary>
    public class PackageDownloadManager
    {
        public PackageDownloadManager(ILoaderWindow loader, List<string> packages, float maxTransferRateKB)
        {
            Uri CurrentXapFile = XapUtil.getCurrentXapFile();
            string PackagesLocation = CurrentXapFile.AbsoluteUri.Remove(CurrentXapFile.AbsoluteUri.LastIndexOf('/') + 1);

            List<Uri> DownloadPackages = new List<Uri>();

            foreach (var package in packages)
            {
                DownloadPackages.Add(new Uri(String.Concat(PackagesLocation, package)));
            }

            // parse the package source list from init params
            init(loader, DownloadPackages, maxTransferRateKB);
        }
        public PackageDownloadManager(ILoaderWindow loader, List<Uri> packageSourceList, float maxTransferRateKB)
        {
            init(loader, packageSourceList, maxTransferRateKB);
        }

        private void init(ILoaderWindow loader, List<Uri> packageSourceList, float maxTransferRateKB)
        {
            // save transfer rate if any
            m_maxTransferRateKB = maxTransferRateKB;
            // save loader callback interface
            m_loader = loader;
            // call init callback with package list
            m_loader.InitCallback(packageSourceList);
            // iterate through list and start downloading the files
            foreach (Uri packageSourceFile in packageSourceList)
            {
                if (maxTransferRateKB > 0)
                    simulateFileDownload(packageSourceFile);
                else
                    downloadFile(packageSourceFile);
            }
        }

        // download file async
        public void downloadFile(Uri source)
        {
            PackageDownloader downloader = new PackageDownloader();
            downloader.Download(source, m_loader);
        }

        // simulate file download for easier testing of the loader
        private void simulateFileDownload(Uri source)
        {
            PackageDownloaderSimulator downloader = new PackageDownloaderSimulator();
            TimeSpan totalDlTime = new TimeSpan(0, 0, 0, 10);
            downloader.download(source, m_loader, m_maxTransferRateKB);
        }

        // data
        ILoaderWindow m_loader;
        float m_maxTransferRateKB;
    }

    /// <summary>
    /// Package downloader class - takes care of the actual download of the packages
    /// </summary>
    public class PackageDownloader
    {
        ILoaderWindow mLoaderWindow;
        WebClient mWebClient;
        Uri mSource;

        public void Download(Uri packageSource, ILoaderWindow progressCallback)
        {
            Abort();
            mLoaderWindow = progressCallback;
            mSource = packageSource;
            mLoaderWindow.DownloadStartCallback(packageSource);

            mWebClient = new WebClient();
            mWebClient.DownloadProgressChanged += (s, e) => mLoaderWindow.DownloadProgressCallback(mSource, new DownloadProgressEventArgs(e));
            mWebClient.OpenReadCompleted += (s, e) => mLoaderWindow.DownloadCompleteCallback(mSource, new DownloadCompleteEventArgs(e));
            mWebClient.OpenReadAsync(packageSource);
        }
        public void Abort()
        {
            if (mWebClient != null)
            {
                mWebClient.DownloadProgressChanged -= onDownloadProgressChanged;
                mWebClient.CancelAsync();
                mWebClient = null;
            }
        }
    }

}
